use crate::model::kline_of::Kline;

///
/// Z-Score Standardization（Z-Score标准化）MACD
///
/// 用于计算每个Kline中macd.macd_v的Z-Score，其中Z-Score是基于到每个Kline位置为止的历史数据（即n-1天的数据）来计算总体标准差的。请注意，此实现直接在每次迭代中更新均值和方差，然后计算Z-Score并更新Kline的macd字段。
///
/// 方差（Variance）计算公式:
///
/// Variance = Σ(xi - μ)^2 / N
///
/// 其中：
/// - Σ表示求和操作
/// - xi表示每个观测值
/// - μ表示观测值的平均数（Mean）
/// - N表示观测值的数量（对于总体标准差计算，直接使用N）
///
/// 基于此公式，我们计算每一天的累计方差来准备后续的Z-Score计算...
///
/// @param klines: Vec<Kline> 待处理的Kline数据集
///
pub fn zscore_macd_iterative(klines: &mut Vec<Kline>) {
    if klines.is_empty() {
        panic!("数据集不能为空");
    }

    let mut means_macd_v = Vec::new(); // 用于存储每天的均值
    let mut std_devs_macd_v = Vec::new(); // 用于存储每天的标准差

    let mut sum_macd_v = 0.0;
    let mut sum_macd_v_squared = 0.0;
    let mut n = 0.0;

    // 预先计算每一天的均值和标准差
    for (_i, kline) in klines.iter().enumerate() {
        if let Some(macd) = &kline.macd {
            sum_macd_v += macd.macd;
            sum_macd_v_squared += macd.macd.powi(2);
            n += 1.0;
        }

        // 在每一天结束时计算并保存均值
        if n > 0.0 {
            let mean_macd_v = sum_macd_v / n;
            means_macd_v.push(mean_macd_v);

            // 计算方差
            let variance_macd_v = if n > 1.0 {
                (sum_macd_v_squared / n) - (mean_macd_v.powi(2))
            } else {
                0.0
            };

            // 计算标准差，这里直接处理除以零的情况
            let std_dev_macd_v = if variance_macd_v > 0.0 {
                variance_macd_v.sqrt()
            } else {
                1.0 // 或者任何合适的默认值
            };
            std_devs_macd_v.push(std_dev_macd_v);
        } else {
            means_macd_v.push(0.0);
            std_devs_macd_v.push(1.0); // 或者任何合适的默认值
        }
    }

    // 使用预先计算的均值和标准差更新每个Kline的macd_zsv
    for (i, kline) in klines.iter_mut().enumerate() {
        if let Some(macd) = &mut kline.macd {
            if std_devs_macd_v[i] != 0.0 {
                macd.macd = (macd.macd - means_macd_v[i]) / std_devs_macd_v[i];
            } else {
                macd.macd = 0.0; // 或者任何合适的处理
            }
        }
    }
}
